package com.coin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.coin.config.IdAutoConfiguration;
import com.coin.domain.*;
import com.coin.feignclient.SysUserFeignClient;
import com.coin.mapper.UserMapper;
import com.coin.member.dto.UserDto;
import com.coin.model.*;
import com.coin.service.*;
import com.coin.vo.UseAuthInfoVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 李力
 * @description 针对表【user(用户表)】的数据库操作Service实现
 * @createDate 2025-06-07 10:16:53
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Autowired
    private UserAuthAuditRecordService userAuthAuditRecordService;

    @Autowired
    private UserAuthInfoService userAuthInfoService;

    @Autowired
    private SysUserFeignClient sysUserFeignClient;

    @Autowired
    private SmsService smsService;

    /**
     * @Description: 查询会员的列表
     * @Author: 李 力
     * @Date: 2025/6/7
     * @Param:
     * @return:
     */
    @Override
    public Page<User> findByPage(Page<User> page, String mobile, Long userId, String userName, String realName, Integer status) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper = wrapper.like(StrUtil.isNotEmpty(mobile), User::getMobile, mobile)
                .eq(userId != null, User::getId, userId)
                .like(StrUtil.isNotEmpty(userName), User::getUsername, userName)
                .like(StrUtil.isNotEmpty(realName), User::getRealName, realName)
                .eq(status != null, User::getStatus, status);
        return page(page, wrapper);
    }

    /**
     * @Description: 修改用户的状态
     * @Author: 李 力
     * @Date: 2025/6/7
     * @Param:
     * @return: R
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(Long id, Byte status) {
        if (id == null || status == null) {
            throw new RuntimeException("参数为空");
        }
        User user = new User();
        user.setId(id);
        user.setStatus(status);
        return updateById(user);
    }

    /**
     * @Description: 修改用户
     * @Author: 李 力
     * @Date: 2025/6/7
     * @Param: user
     * @return: R
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUser(User user) {
        if (user == null) {
            throw new RuntimeException("参数为空");
        }
        return updateById(user);
    }

    /**
     * @Description: 获取用户的详情
     * @Author: 李 力
     * @Date: 2025/6/7
     * @Param: id
     * @return: R
     */
    @Override
    public User getUserInfo(Long id) {
        if (id == null) {
            throw new RuntimeException("参数为空");
        }
        return getById(id);
    }

    /**
     * @Description: 查询该用户邀请的用户列表
     * @Author: 李 力
     * @Date: 2025/6/7
     * @Param: page userId:被邀请用户的id
     * @return: R
     */
    @Override
    public Page<User> findDirectInvitePage(Page<User> page, Long userId) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper = queryWrapper.eq(userId != null, User::getDirectInviteid, userId);
        return page(page, queryWrapper);
    }

    /**
     * @Description: 查询用户的审核列表
     * @Author: 李 力
     * @Date: 2025/6/7
     * @Param:
     * @return: R
     */
    @Override
    public Page<User> findUserAuths(Page<User> page, String mobile, Long userId, String userName, String realName, Integer reviewsStatus) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper = queryWrapper.like(StrUtil.isNotEmpty(mobile), User::getMobile, mobile)
                .eq(userId != null, User::getId, userId)
                .like(StrUtil.isNotEmpty(userName), User::getUsername, userName)
                .like(StrUtil.isNotEmpty(realName), User::getRealName, realName)
                .eq(reviewsStatus != null, User::getReviewsStatus, reviewsStatus);
        return page(page, queryWrapper);
    }

    /**
     * @Description: 查询用户的认证详情
     * @Author: 李 力
     * @Date: 2025/6/7
     * @Param:
     * @return: R
     */
    @Override
    public UseAuthInfoVo getUseAuthInfo(Long id) {
        if (id == null) {
            throw new RuntimeException("参数为空");
        }
        //1.查询用户
        User user = getById(id);
        if (user == null) {
            throw new RuntimeException("无此用户");
        }
        //2.查询用户审核记录
        List<UserAuthAuditRecord> authAuditRecordList = null;
        Integer reviewsStatus = user.getReviewsStatus();
        List<UserAuthInfo> userAuthInfoList = null;
        if (reviewsStatus == null || reviewsStatus == 0) {
            //待审核状态则没有审核记录
            authAuditRecordList = Collections.emptyList();
            //没有审核记录也会有认证记录
            userAuthInfoList = userAuthInfoService.getUserAuthInfoByUserId(id);
        } else {
            //查询审核记录
            authAuditRecordList = userAuthAuditRecordService.getUserAuthAuditRecordList(id);
            //3.查询用户的认证详情列表
            UserAuthAuditRecord userAuthAuditRecord = authAuditRecordList.get(0);
            Long authCode = userAuthAuditRecord.getAuthCode();
            userAuthInfoList = userAuthInfoService.getUserAuthInfoByCode(authCode);
        }
        return new UseAuthInfoVo(user, userAuthInfoList, authAuditRecordList);
    }

    /**
     * @Description: 审核
     * @Author: 李 力
     * @Date: 2025/6/9
     * @Param: Long id, Byte authStatus, Long authCode, String remark
     * @return: R
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserAuthStatus(Long id, Byte authStatus, Long authCode, String remark) {
        if (id == null || authStatus == null || authCode == null) {
            throw new RuntimeException("必要参数为空");
        }
        User user = getById(id);
        if (user == null) {
            throw new RuntimeException("查无此用户");
        }
        //审核状态
        user.setReviewsStatus(authStatus.intValue());
        //修改用户审核状态
        boolean result = updateById(user);
        if (result) {
            //审核表里面插入数据
            UserAuthAuditRecord userAuthAuditRecord = new UserAuthAuditRecord();
            userAuthAuditRecord.setUserId(id);
            userAuthAuditRecord.setStatus(authStatus);
            userAuthAuditRecord.setAuthCode(authCode);
            String userId = SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString();
            userAuthAuditRecord.setAuditUserId(Long.valueOf(userId)); // 审核人的ID
            R<String> r = sysUserFeignClient.getUserNameById(Long.valueOf(userId));
            String userName = r.getData();
            userAuthAuditRecord.setAuditUserName(userName);
            userAuthAuditRecord.setRemark(remark);
            return userAuthAuditRecordService.save(userAuthAuditRecord);
        }
        return false;
    }

    /**
     * @Description: 实名身份认证
     * @Author: 李 力
     * @Date: 2025/6/10
     * @Param:
     * @return: R
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean infoCheck(Long userId, UserAuthForm userAuthForm) {
        if (userId == null || userAuthForm == null || userAuthForm.getIdCard() == null || userAuthForm.getRealName() == null) {
            throw new RuntimeException("必要参数为空");
        }
        User user = getById(userId);
        if (user == null) {
            throw new RuntimeException("无此用户");
        }
        String authStatus = Byte.toString(user.getAuthStatus());
        if (!"0".equals(authStatus)) {
            throw new RuntimeException("该用户已完成认证");
        }
        //执行认证
        boolean check = IdAutoConfiguration.check(userAuthForm.getRealName(), userAuthForm.getIdCard());
        if (!check) {
            throw new RuntimeException("认证信息错误，请检查");
        }
        //更改状态
        user.setAuthtime(new Date());
        user.setAuthStatus((byte) 1);
        user.setRealName(userAuthForm.getRealName());
        user.setIdCard(userAuthForm.getIdCard());
        user.setIdCardType(userAuthForm.getIdCardType());
        return updateById(user);
    }

    /**
     * @Description: 获取当前登录用户的详情
     * @Author: 李 力
     * @Date: 2025/6/10
     * @Param:
     * @return: R
     */
    @Override
    public User getCurrentUserInfo(Long userId) {
        User user = getUserInfo(userId);
        if (user == null) {
            throw new RuntimeException("查无此用户");
        }
        Byte seniorAuthStatus = null;
        String seniorAuthDesc = null;
        Integer reviewsStatus = user.getReviewsStatus();
        if (reviewsStatus == null) {
            seniorAuthStatus = 3;
            seniorAuthDesc = "资料未填写";
        } else {
            switch (reviewsStatus) {
                case 1:
                    seniorAuthStatus = 1;
                    seniorAuthDesc = "审核通过";
                    break;
                case 2:
                    seniorAuthStatus = 2;
                    // 查询被拒绝的原因--->审核记录里面的
                    // 时间排序,
                    List<UserAuthAuditRecord> userAuthAuditRecordList = userAuthAuditRecordService.getUserAuthAuditRecordList(user.getId());
                    if (userAuthAuditRecordList != null && !userAuthAuditRecordList.isEmpty()) {
                        UserAuthAuditRecord userAuthAuditRecord = userAuthAuditRecordList.get(0);
                        seniorAuthDesc = userAuthAuditRecord.getRemark();
                    }
                    seniorAuthDesc = "原因未知";
                    break;
                case 0:
                    seniorAuthStatus = 0;
                    seniorAuthDesc = "等待审核";
                    break;
            }
        }
        user.setSeniorAuthStatus(seniorAuthStatus);
        user.setSeniorAuthDesc(seniorAuthDesc);
        return user;
    }

    /**
     * @Description: 修改手机号码
     * @Author: 李 力
     * @Date: 2025/6/11
     * @Param:
     * @return: R
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePhone(Long userId, UpdatePhoneParam updatePhoneParam) {
        if (userId == null || updatePhoneParam == null) {
            throw new RuntimeException("参数为空");
        }
        User user = getById(userId);
        if (user == null) {
            throw new RuntimeException("无此用户");
        }
        String oldMobile = user.getMobile();
        String newMobilePhone = updatePhoneParam.getNewMobilePhone();
        if (oldMobile.equals(newMobilePhone)) {
            throw new RuntimeException("手机号码和修改一致，无需修改");
        }
        //给旧的手机发送验证码
        Sms sms = new Sms();
        sms.setMobile(oldMobile);
        sms.setContent("就手机:123456");
        sms.setCountryCode(updatePhoneParam.getCountryCode());
        boolean oldResult = smsService.sendMsg(sms);
        if (!oldResult) {
            throw new RuntimeException("旧手机验证码发送失败");
        }
        //校验旧手机验证码
        if (!"123456".equals(updatePhoneParam.getOldValidateCode())) {
            throw new RuntimeException("旧手机验证码错误");
        }
        //校验新的手机号码是否可用
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper = queryWrapper.eq(StrUtil.isNotEmpty(updatePhoneParam.getNewMobilePhone()), User::getMobile, updatePhoneParam.getNewMobilePhone())
                .eq(StrUtil.isNotEmpty(updatePhoneParam.getCountryCode()), User::getCountryCode, updatePhoneParam.getCountryCode());
        long count = count(queryWrapper);
        if (count > 0) {
            throw new RuntimeException("手机号已被占用");
        }
        //给新手机号码发送短信
        Sms sms1 = new Sms();
        sms1.setMobile(newMobilePhone);
        sms1.setContent("新手机:654321");
        sms1.setCountryCode(updatePhoneParam.getCountryCode());
        boolean newResult = smsService.sendMsg(sms1);
        if (!newResult) {
            throw new RuntimeException("新手机验证码发送失败");
        }
        if (!"654321".equals(updatePhoneParam.getValidateCode())) {
            throw new RuntimeException("新手机验证码错误");
        }
        //最后修改手机号码
        user.setMobile(updatePhoneParam.getNewMobilePhone());
        return updateById(user);
    }

    /**
     * @Description: 修改登录密码
     * @Author: 李 力
     * @Date: 2025/6/11
     * @Param:
     * @return: R
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateLoginPwd(Long userId, updateLoginParam updateLoginParam) {
        if (userId == null || updateLoginParam == null ||
                StrUtil.isEmpty(updateLoginParam.getNewPassword())
                || StrUtil.isEmpty(updateLoginParam.getOldPassword())
                || StrUtil.isEmpty(updateLoginParam.getValidateCode())
        ) {
            throw new RuntimeException("必要参数为空");
        }
        User user = getById(userId);
        if (user == null) {
            throw new RuntimeException("无此用户");
        }
        //校验旧的密码
        String oldPassword = updateLoginParam.getOldPassword();
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String password = user.getPassword();
        boolean matches = bCryptPasswordEncoder.matches(oldPassword, password);
        if (!matches) {
            throw new RuntimeException("原始密码输入错误");
        }
        //校验手机号
        if (!"123456".equals(updateLoginParam.getValidateCode())) {
            throw new RuntimeException("手机验证码错误");
        }
        //修改密码
        String newPwd = bCryptPasswordEncoder.encode(updateLoginParam.getNewPassword());
        user.setPassword(newPwd);
        return updateById(user);
    }

    /**
     * @Description: 修改交易密码
     * @Author: 李 力
     * @Date: 2025/6/11
     * @Param: updateLoginParam
     * @return: R
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePayPwd(Long userId, updateLoginParam updateLoginParam) {
        if (userId == null || updateLoginParam == null ||
                StrUtil.isEmpty(updateLoginParam.getNewPassword())
                || StrUtil.isEmpty(updateLoginParam.getOldPassword())
                || StrUtil.isEmpty(updateLoginParam.getValidateCode())
        ) {
            throw new RuntimeException("必要参数为空");
        }
        User user = getById(userId);
        if (user == null) {
            throw new RuntimeException("无此用户");
        }
        //校验旧的密码
        String oldPassword = updateLoginParam.getOldPassword();
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String password = user.getPaypassword();
        boolean matches = bCryptPasswordEncoder.matches(oldPassword, password);
        if (!matches) {
            throw new RuntimeException("原始交易密码输入错误");
        }
        //校验手机号
        if (!"123456".equals(updateLoginParam.getValidateCode())) {
            throw new RuntimeException("手机验证码错误");
        }
        //修改密码
        String newPwd = bCryptPasswordEncoder.encode(updateLoginParam.getNewPassword());
        user.setPaypassword(newPwd);
        return updateById(user);
    }

    /**
     * @Description: 给管理服务提供远程调用
     * @Author: 李 力
     * @Date: 2025/6/11
     * @Param: ids
     * @return: R
     */
    @Override
    public List<UserDto> getBasicUsers(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new RuntimeException("参数为空");
        }
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper = queryWrapper.in(User::getId, ids);
        List<User> source = list(queryWrapper);
        if (CollectionUtil.isEmpty(source)) {
            return new ArrayList<>();
        }
        List<UserDto> collect = source.stream().map(s -> {
            UserDto t = new UserDto();
            BeanUtil.copyProperties(s, t);
            return t;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * @Description: 用户的注册
     * @Author: 李 力
     * @Date: 2025/6/11
     * @Param:
     * @return: R
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(RegisterParam registerParam) {
        if (registerParam == null) {
            throw new RuntimeException("参数为空");
        }
        //参数字段校验略过
        String mobile = registerParam.getMobile();
        String email = registerParam.getEmail();
        if (StrUtil.isEmpty(mobile) && StrUtil.isEmpty(email)) {
            throw new RuntimeException("手机号或者邮箱不能同时为空");
        }
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper = queryWrapper.eq(User::getMobile, mobile)
                .eq(User::getEmail, email);
        long count = count(queryWrapper);
        if (count > 0) {
            throw new RuntimeException("手机号码或者邮箱已被注册");
        }
        User user = getUser(registerParam);
        return save(user);
    }

    private User getUser(RegisterParam registerParam) {
        User user = new User();
        user.setCountryCode(registerParam.getCountryCode());
        user.setEmail(registerParam.getEmail());
        user.setMobile(registerParam.getMobile());
        String encodePwd = new BCryptPasswordEncoder().encode(registerParam.getPassword());
        user.setPassword(encodePwd);
        user.setPaypassSetting(false);
        user.setStatus((byte) 1);
        user.setType((byte) 1);
        user.setAuthStatus((byte) 0);
        user.setLogins(0);
        user.setInviteCode(RandomUtil.randomString(6)); // 用户的邀请码
        if (!StrUtil.isEmpty(registerParam.getInvitionCode())) {
            User userPre = getOne(new LambdaQueryWrapper<User>().eq(User::getInviteCode, registerParam.getInvitionCode()));
            if (userPre != null) {
                user.setDirectInviteid(String.valueOf(userPre.getId())); // 邀请人的id , 需要查询
                user.setInviteRelation(String.valueOf(userPre.getId())); // 邀请人的id , 需要查询
            }
        }
        return user;
    }


    /**
     * @Description: 给财务系统提供远程调用
     * @Author: 李 力
     * @Date: 2025/6/13
     * @Param:
     * @return: R
     */
    @Override
    public Map<Long, UserDto> getBasicUsers2(List<Long> ids, String userName, String mobile) {
        if (CollectionUtil.isEmpty(ids) && StrUtil.isEmpty(userName) && StrUtil.isEmpty(mobile)) {
            return Collections.emptyMap();
        }
        List<User> source = list(new LambdaQueryWrapper<User>()
                .in(!CollectionUtil.isEmpty(ids), User::getId, ids)
                .like(!StrUtil.isEmpty(userName), User::getUsername, userName)
                .like(!StrUtil.isEmpty(mobile), User::getMobile, mobile));
        if (CollectionUtil.isEmpty(source)) {
            return Collections.emptyMap();
        }
        List<UserDto> userDtos = source.stream().map(s -> {
            UserDto t = new UserDto();
            BeanUtil.copyProperties(s, t);
            return t;
        }).collect(Collectors.toList());
        return userDtos.stream().collect(Collectors.toMap(UserDto::getId, userDto -> userDto));
    }
}



